package com.manong.config.security;

import com.manong.config.security.filter.CheckTokenFilter;
import com.manong.config.security.handler.AnonymousAuthenticationHandler;
import com.manong.config.security.handler.CustomerAccessDeniedHandler;
import com.manong.config.security.handler.LoginFailureHandler;
import com.manong.config.security.handler.LoginSuccessHandler;
import com.manong.config.security.service.CustomerUserDetailsService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration    //配置类
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  @Resource
  private CustomerUserDetailsService customerUserDetailsService;
  @Resource
  private LoginSuccessHandler loginSuccessHandler;
  @Resource
  private LoginFailureHandler loginFailureHandler;
  @Resource
  private AnonymousAuthenticationHandler anonymousAuthenticationHandler;
  @Resource
  private CustomerAccessDeniedHandler customerAccessDeniedHandler;
  @Resource
  private CheckTokenFilter checkTokenFilter;
  
  @Value("${request.login.url}")
  private String loginURL;
  
  /*** 注入加密处理类
   *
   * @return
   */
  @Bean
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
  
  /**
   * 配置认证处理器
   *
   * @param http
   * @throws Exception
   */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
//登录前进行过滤
    http.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class);
    
    http.formLogin()    //表单登录
      .loginProcessingUrl(loginURL)  //登录提交地址接口
// 设置登录验证成功或失败后的的跳转地址
      .successHandler(loginSuccessHandler)  //成功跳转
      .failureHandler(loginFailureHandler) //失败跳转
// 禁用csrf防御机制
      .and().csrf().disable()
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)  //不创建Session
      .and()
      .authorizeRequests()  //设置需要拦截的请求
      .antMatchers("/api/user/login").permitAll() //登录请求放行
      .anyRequest().authenticated() //其他一律请求都要进行身份认证
      .and()
      .exceptionHandling() //异常时,即身份认证失败
      .authenticationEntryPoint(anonymousAuthenticationHandler) //匿名无权限访问
      .accessDeniedHandler(customerAccessDeniedHandler) //认证用户无权限访问
      .and().cors();//开启跨域配置
  }
  
  /**
   * 配置认证处理器
   *
   * @param auth
   * @throws Exception
   */
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //passwordEncoder密码加密
    auth.userDetailsService(customerUserDetailsService).passwordEncoder(passwordEncoder());
  }
}

